import React, { useEffect, useState } from 'react';
import { Card, Empty, Space, Checkbox } from 'antd';
import { CardProps } from 'antd/lib/card';
import { useField, observer, useFieldSchema, RecursionField } from '@formily/react';
import cls from 'classnames';
import { ISchema } from '@formily/json-schema';
import { usePrefixCls } from './usePrefixCls';
import { ArrayBase, ArrayBaseMixins } from '../array-base';
import { formatMessage } from '@/utils/i18n-transform';

import { CheckboxChangeEvent } from 'antd/lib/checkbox/Checkbox';

interface ArrayCardsProps extends CardProps {
  checkboxAble?: boolean;
  transformMap?: Object;
  defaultVal?: boolean;
}

type ComposedArrayCards = React.FC<ArrayCardsProps> & ArrayBaseMixins;

const isAdditionComponent = (schema: ISchema) => {
  return schema['x-component']?.indexOf('Addition') > -1;
};

const isIndexComponent = (schema: ISchema) => {
  return schema['x-component']?.indexOf('Index') > -1;
};

const isRemoveComponent = (schema: ISchema) => {
  return schema['x-component']?.indexOf('Remove') > -1;
};

const isMoveUpComponent = (schema: ISchema) => {
  return schema['x-component']?.indexOf('MoveUp') > -1;
};

const isMoveDownComponent = (schema: ISchema) => {
  return schema['x-component']?.indexOf('MoveDown') > -1;
};

const isMoveCopyComponent = (schema: ISchema) => {
  return schema['x-component']?.indexOf('Copy') > -1;
};

const isDeleteComponent = (schema: ISchema) => {
  return schema['x-component']?.indexOf('Delete') > -1;
};
const isOpenLibComponent = (schema: ISchema) => {
  return schema['x-component']?.indexOf('OpenLib') > -1;
};
const isSalerWtdwlComponent = (schema: ISchema) => {
  return schema['x-component']?.indexOf('SalerWtdwl') > -1;
};
const isOperationComponent = (schema: ISchema) => {
  return (
    isAdditionComponent(schema) ||
    isRemoveComponent(schema) ||
    isMoveDownComponent(schema) ||
    isMoveUpComponent(schema) ||
    isMoveCopyComponent(schema) ||
    isDeleteComponent(schema) ||
    isOpenLibComponent(schema) ||
    isSalerWtdwlComponent(schema)
  );
};

export const ArrayCards: ComposedArrayCards = observer((props) => {
  const field = useField<Formily.Core.Models.ArrayField>();
  const schema = useFieldSchema();
  let dataSource = Array.isArray(field.value) ? field.value : [];
  const prefixCls = usePrefixCls('formily-array-cards', props);
  const { checkboxAble, editable } = props || {};
  if (!schema) throw new Error('can not found schema object');

  const [indeterminate, setIndeterminate] = useState(false);

  const [checkAll, setCheckAll] = useState(false);

  const [checkIndex, setCheckIndex] = useState<number[]>([]);

  useEffect(() => {
    if (props.defaultVal && field.visible) {
      props?.onChange?.([{}]);
    }
  }, [props.defaultVal]);

  const handleBatchDelete = (array) => {
    checkIndex.sort().forEach((i, index) => {
      array.field?.remove?.(i - index);
      array.props?.onRemove?.(i - index);
    });

    setCheckIndex([]);

    setIndeterminate(false);
    setCheckAll(false);

    // props?.onChange?.(nowValue);
  };

  const handleValueChange = () => {
    const nowValue = field.value;

    setIndeterminate(!!checkIndex?.length && checkIndex?.length < nowValue?.length);
    setCheckAll(checkIndex?.length === nowValue?.length);
  };

  const handleCheckAllChange = (e: CheckboxChangeEvent) => {
    const checked = e.target.checked;
    setCheckIndex(checked ? dataSource.map((_, index) => index) : []);
    setIndeterminate(false);
    setCheckAll(checked);
  };

  const handleCheckboxGroupChange = (checkedValue: number[]) => {
    setCheckIndex(checkedValue);

    setIndeterminate(!!checkedValue.length && checkedValue.length < dataSource.length);
    setCheckAll(checkedValue.length === dataSource.length);
  };

  const renderItems = (checkbox: boolean) => {
    // fix: 兼容详情转换逻辑
    if (props?.transformMap) {
      for (let i = 0; i < props?.value?.length; i++) {
        Object.keys(props?.transformMap).forEach((key: any) => {
          props.value[i][key] = props?.value[i][props?.transformMap[key]];
        });
      }
    }
    return dataSource?.map((item, index) => {
      const items = Array.isArray(schema.items)
        ? schema.items[index] || schema.items[0]
        : schema.items;
      console.log('items123', items);
      const title = (
        <span>
          <Space>
            {checkbox ? <Checkbox value={index} /> : null}
            <RecursionField
              schema={items}
              name={index}
              filterProperties={(schema) => {
                return isIndexComponent(schema);
              }}
              onlyRenderProperties
            />
            {props.title || field.title}
          </Space>
        </span>
      );
      const extra = (
        <span>
          <RecursionField
            schema={items}
            name={index}
            filterProperties={(schema) => {
              return isOperationComponent(schema);
            }}
            onlyRenderProperties
          />
          {props.extra}
        </span>
      );
      const content = (
        <RecursionField
          schema={items}
          name={index}
          filterProperties={(schema) => {
            if (isIndexComponent(schema)) return false;
            return !isOperationComponent(schema);
          }}
        />
      );
      return (
        <ArrayBase.Item
          key={index}
          index={index}
          onValueChange={handleValueChange}
          onBatchDelete={handleBatchDelete}
        >
          <Card
            {...props}
            onChange={() => {}}
            className={cls(`${prefixCls}-item`, props.className)}
            title={title}
            extra={extra}
          >
            {content}
          </Card>
        </ArrayBase.Item>
      );
    });
  };

  const renderAddition = () => {
    return schema.reduceProperties((addition, schema) => {
      if (isAdditionComponent(schema)) {
        return addition.concat((<RecursionField schema={schema} name="addition" />) as any);
      }
      if (isDeleteComponent(schema)) {
        return addition.concat((<RecursionField schema={schema} name="delete" />) as any);
      }
      if (isOpenLibComponent(schema)) {
        return addition.concat((<RecursionField schema={schema} name="open" />) as any);
      }
      if (isSalerWtdwlComponent(schema)) {
        return addition.concat((<RecursionField schema={schema} name="saler" />) as any);
      }
      return addition;
    }, []);
  };

  const renderEmpty = () => {
    if (dataSource?.length) return;
    return (
      <Card
        {...props}
        onChange={() => {}}
        className={cls(`${prefixCls}-item`, props.className)}
        title={props.title || field.title}
      >
        <Empty />
      </Card>
    );
  };

  const btn = renderAddition();

  if (checkboxAble && editable) {
    return (
      <ArrayBase onValueChange={handleValueChange} onBatchDelete={handleBatchDelete}>
        <Space size="large" className="ant-formily-array-base-wrap">
          <Checkbox
            indeterminate={indeterminate}
            onChange={handleCheckAllChange}
            checked={checkAll}
            disabled={!dataSource.length}
          >
            {formatMessage('checkbox.check.all')}
          </Checkbox>

          {btn}
        </Space>

        {renderEmpty()}
        <Checkbox.Group
          value={checkIndex}
          style={{ width: '100%' }}
          onChange={handleCheckboxGroupChange}
        >
          {renderItems(true)}
        </Checkbox.Group>
      </ArrayBase>
    );
  }

  return (
    <ArrayBase>
      <Space size="large">{btn}</Space>

      {renderEmpty()}

      {renderItems(false)}
    </ArrayBase>
  );
});
ArrayCards.displayName = 'ArrayCards';
ArrayBase.mixin(ArrayCards);

export default ArrayCards;
